using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using TagTool.Devices.DataStructures;
using TagTool.GraphicTypes;

namespace TagTool.Devices.Joystick
{
    public delegate void JoystickEventHandler(object sender, JoystickDeviceEventArgs e);

    public class JoystickDevice : IPointingDevice
    {
        private uint deviceId;
        private string name = "Joystick";
        private JoystickInfo info;
        private uint period;
        private WinJoystickForm form;
        private uint buttons;
        private PointD location;
        private PointD rudder;
        private JoystickExtInfo infoExt;
        private uint sizeOfInfo;

        private JoystickDeviceEventArgs args;

        public event JoystickEventHandler JoystickEvent;

        public JoystickDevice(uint deviceId)
        {
            this.deviceId = deviceId;
            period = 100;
            rudder = new PointD();
            info = new JoystickInfo();
            form = new WinJoystickForm(this);
            location = new PointD();
            args = new JoystickDeviceEventArgs();
            infoExt = new JoystickExtInfo();
            sizeOfInfo = (uint)Marshal.SizeOf(infoExt);
            infoExt.Size = sizeOfInfo;
            infoExt.Flags = (uint)JoystickExtInfoFlag.ReturnAll;
            OnJoystickEvent();
        }

        ~JoystickDevice()
        {
            Disconnect();
        }

        #region IDevice Member

        public void Connect()
        {
            WinJoystick.SetCapture(form.Handle, deviceId, period, false);
        }

        public void Disconnect()
        {
            WinJoystick.ReleaseCapture(deviceId);
        }

        public string Name
        {
            get { return name; }
        }
        
        public PointD Rudder
        {
            get { return rudder; }
        }

        public int DeviceId
        {
            get { return (int)deviceId; }
        }

        public bool Available
        {
            get
            {
               return (WinJoystick.GetPos(deviceId, ref info) == MMResult.NoError);
            }
        }

        #endregion

        #region IPointingDevice Member

        public double X
        {
            get { return location.X; }
        }

        public double Y
        {
            get { return location.Y; }
        }

        public double Z
        {
            get { return location.Z; }
        }

        public uint Buttons
        {
            get { return buttons; }
        }

        public PointD Location
        {
            get { return location; }
        }

        public DeviceResolution Resolution
        {
            get { return null; }
        }

        #endregion

        public void OnJoystickEvent()
        {
            WinJoystick.GetPosEx((uint)deviceId, ref infoExt);

            location.X = args.X = infoExt.X;
            location.Y = args.Y = infoExt.Y;
            //location.Z = args.Z = infoExt.Z;
            rudder.X = args.Rudder.X = infoExt.Z;
            rudder.Y = args.Rudder.Y = infoExt.Rudder;
            
            buttons = args.Buttons = (uint)infoExt.Buttons;

            if (JoystickEvent != null)
            {
                JoystickEvent(this, args);
            }

        }
    }
}
